<?php

/**
 * @Author: king
 * @Date:   2019-05-04 16:46:12
 * @Last Modified by:   king
 * @Last Modified time: 2019-06-07 23:00:33
 */
namespace App\Models\Api;
use App\Exceptions\ApiException;
use App\Models\Api\LanmeiCounselor;
use App\Models\Api\LanmeiTag;
use App\Models\Api\LanmeiCounselorAnswer;
use App\Models\Api\LanmeiCounselorProblem;
use App\Models\Api\LanmeiCounselorInform;
use App\Models\Api\LanmeiCounselorAnswerComment;
use App\Models\Api\LanmeiCounselorAnswerOnlooker;
use App\Models\Api\Base;
use AstroTool\Cache\CacheManage;
use Cache;
use DB;

class LanmeiCounselorAnswer extends Base
{
    protected $table = 'counselor_answer';
    protected $dateFormat = 'U';
    public $guarded       = [];
    const CREATED_AT      = 'create_time';
    const UPDATED_AT      = 'update_time';
    public $timestamps    = true;

    /**
     * 获取最近一周前二十咨询师的排名情况
     * @return array|bool
     * @throws \Exception
     */
    public function getWeekBestCounselor($myCounselo = [])
    {
        $time = strtotime('-7 days', time());
        $where = [['cn.create_time','>', $time], 'cn.state' => 0];
        try
        {
            $info = $this
                ->from('counselor_answer as cn')
                ->join('counselor as c', 'cn.c_id','=','c.id', 'INNER')
                ->select("c.id", 'c.accept','cn.c_id')
                ->where(['cn.state'=>0])
                ->paginate(20)->toArray();
        }
        catch (\Exception $e)
        {
            
            throw new ApiException('获取咨询师回答次数失败', 200, config('code.error'));
        }
        $arr['list_data'] = [];
        $arr['my_data'] = null;
        if ($info['data'])
        {
            foreach ($info['data'] as $k => $datum)
            {
                $counserinfo = (new LanmeiCounselor())->getInfoById($datum['id']);
                $arr['list_data'][] = [
                    'avatar' => $counserinfo['avatar'],
                    'nickname' => $counserinfo['nickname'],
                    'accept' => $counserinfo['accept'],
                    'grab_num' => $datum['c_id'] ??'', //暂时count
                    'divination_level' => $counserinfo['divination_level'],
                    'stargazer_level' => $counserinfo['stargazer_level'],
                    'cid' => $counserinfo['stargazer_level']
                ];

                if ($myCounselo['id'] == $datum['id'])
                {
                    $arr['my_data'] = [
                        'avatar' => 1,
                        'nickname' => '',
                        'accept' => 1,
                        'grab_num' => 1,
                        'divination_level' => 1,
                        'stargazer_level' => 1,
                        'ranking' => 1,
                        'cid' => 2
                    ];
                }
            }

        }
        return $arr;
    }


    /**
     * 统计当前咨询师采纳的答案数
     * @param int $cid
     * @return bool|int|string
     */
    public function getCountAcceptAnswer($cid = 0)
    {
        $where = ['c_id' => $cid, 'is_accept' => 1, 'state' => 0];
        try
        {

            $data = $this->where($where)->count('id');
        }
        catch (\Exception $e)
        {
            throw new ApiException('获取咨询师被采纳的答案失败', 200, config('code.error'));
        }

        return $data;
    }

    /**
     * 统计当前咨询师所有答案数
     * @param int $cid
     * @return bool|int|string
     */
    public function getCountAllAnswer($cid = 0)
    {
        $where = ['c_id' => $cid];
        try
        {

            $data = $this->where($where)->count('id');
        }
        catch (\Exception $e)
        {
           throw new ApiException('获取咨询师被采纳的答案失败', 200, config('code.error'));
        }

        return $data;
    }


    /**
     * 问题详情 -- 通过答案ID 获取答案详情
     * @param $caIds
     * @param int $cid
     * @return array
     * @throws \Exception
     */
    public function getAnswerByCpid($caIds, $cid = 0)
    {
        // 获取咨询师ID
        $cids = [];
        $resultData = [];
        if ($caIds)
        {
            $answerData = $this->batchGetInfoByIds($caIds, 'id,create_time,c_id,answer_type,answer_content,status,is_accept,read_num,is_comment,state,duration');
            foreach ($answerData as $answerItem)
            {
                array_push($cids, $answerItem['c_id']);
            }
            // 获取咨询师头像信息
            $counselorData = (new LanmeiCounselor())->batchGetInfoByIds($cids, 'avatar,nickname');
            ksort($answerData);

            // 组合答案数据
            foreach ($answerData as $answerItem)
            {
                if ($answerItem['status'] == 0 && $cid = $answerItem['c_id']) continue;

                $resultData[] = [
                    'c_id' => $answerItem['c_id'],
                    'avatar' => $counselorData[$answerItem['c_id']]['avatar'],
                    'nickname' => $counselorData[$answerItem['c_id']]['nickname'],
                    'time' => date($answerItem['create_time']),
                    'type' => $answerItem['answer_type'],
                    'content' => $answerItem['answer_content'],
                    'ca_id' => $answerItem['id'],
                    'is_comment' => $answerItem['is_comment'],
                    'duration' => $answerItem['duration'],
                    'state' => $answerItem['state'],
                    'read_num' => $answerItem['read_num']
                ];
            }
        }

        return ['cids' => $cids, 'info' => $resultData];
    }

    /**
     * 回答问题
     * @param $data array 答案数据
     * @param $type int 答题类型 1指定 2抢答 3普通
     * @param $problemInfo
     * @return array
     * @throws \Exception
     */
    public function answerToProblem($data, $type, $problemInfo)
    {
        \DB::beginTransaction();
        try
        {
            $time = time();
            $answerData = [
                'create_time' => $time,
                'answer_type' => $data['answer_type'],
                'answer_content' => $data['answer_content'],
                'duration' => $data['duration'],
                'sort' => $time,
                'state' => 0
            ];

            $problemModel = new LanmeiCounselorProblem();

            $problemUpdateData = [
                'id' => $data['cp_id'],
                'answer_people' => $problemInfo['answer_people']
            ];
            switch ($type)
            {
                case 1: // 指定
                    // 更新答案
                    $res = $this->save($answerData, ['cp_id' => $data['cp_id'], 'c_id' => $data['c_id']]);
                    break;
                default:
                    $answerData['cp_id'] = $data['cp_id'];
                    $answerData['c_id'] = $data['c_id'];
                    $res = $this->create($answerData);
                    // 添加要更新的答案ID【问题表中的】
                    $anIds = explode(',', $problemInfo['answer_ids']);
                    array_push($anIds, $res->id);

                    $problemUpdateData['answer_ids'] = implode(',', $anIds);;
            }
            // 判断是否回答人数达标 进入结算状态
            if ($problemInfo['people'] <= ($problemInfo['answer_people'] + 1))
            { // 如果答题人数已满
                $problemUpdateData['pad_time'] = $time;
                $problemUpdateData['problem_status'] = 4;
            }

            // 更新已经回答人数
            $updateRes = $problemModel->update($problemUpdateData);
            // 全部执行成功
            if ($res && $updateRes)
            {
                \DB::commit();
                // 更新问题缓存
                CacheManage::getInstance()->setCacheConfig('user_problem', $problemUpdateData['id'])
                    ->setCache($problemUpdateData, 'details', true);
                $result = ['status' => true, 'msg' => ''];
            } else
            {
                \DB::rollback();
                $result = ['status' => false, 'msg' => '服务异常，请稍后再试...'];
            }
        }
        catch (Exception $e)
        {
            \DB::rollback();
             \Log::info($e->getMessage());
            $result = ['status' => false, 'msg' => '服务异常，请稍后再试...'];
        }

        return $result;
    }

    /**
     * 问题采纳
     * @param $caId
     * @param $uid
     * @throws \Exception
     */
    public function accept($caId, $uid)
    {
        // 查询答案信息
        $answerData = current($this->batchGetInfoByIds($caId, 'cp_id,state,c_id,uid'));
        if (!$answerData && $answerData['uid'] != $uid)
        {
            throw new ApiException('答案不存在', config('code.error'));
        }
        if ($answerData['state'] !== 0)
        {
            $msg = in_array($answerData['state'], [1, 4]) ? '采纳失败！答案已举报...' : '答案不存在';
            throw new ApiException($msg, config('code.error'));
        }

        $problemModel = new LanmeiCounselorProblem();
        // 获取问题信息
        $problemData = $problemModel->getProblemInfoById($answerData['cp_id'], 'id,uid,problem_status,accept_answer');

        if ($problemData['uid'] != $uid)
        {   // 判断问题是不是自己的
            throw new ApiException('问题不存在', config('code.error'));
        }

        if (!in_array($problemData['problem_status'], [3, 4]))
        {
            throw new ApiException('采纳失败！问题不在可采纳状态...', config('code.error'));
        }

        if ($problemData['accept_answer'])
        {
            throw new ApiException('问题已经采纳过答案了！', config('code.error'));
        }

        \DB::beginTransaction();
        try
        {
            $caUpdata = [
                'is_accept' => 1,
                'accept_time' => time()
            ];
            // 更新问题信息
            $problemModel->save(['accept_answer' => $caId], ['id' => $problemData['id']]);
            // 更新答案信息
            $this->save($caUpdata, ['id' => $caId]);

            \DB::commit();
        }
        catch (Exception $e)
        {
            \DB::rollback();
            throw new ApiException('服务异常，采纳失败！', 200, config('code.error'));
        }

        // 更新问题缓存
        CacheManage::getInstance()->setCacheConfig('user_problem', $problemData['id'])
            ->setCache(['accept_answer' => $caId], 'details', true);
        // 更新答案缓存
        CacheManage::getInstance()->setCacheConfig('counselor_problem_answer', $caId)
            ->setCache($caUpdata, 'details', true);
    }

    /**
     * 答案举报
     * @param $caId
     * @param $tid
     * @param $content
     * @param $uid
     * @throws Exception
     * @throws \Exception
     */
    public function answerInform($caId, $tid, $content, $uid)
    {
        // 获取答案信息
        $answerState = current($this->batchGetInfoByIds($caId, 'cp_id,state'));

        if (!$answerState || in_array($answerState['state'], [2, 3]))
        {
            throw new ApiException('答案不存在', 200, config('code.error'));
        }

        if (in_array($answerState['state'], [1, 4]))
        {
            throw new ApiException('答案已举报', 200, config('code.error'));
        }
        // 获取答案信息
        $problemData = (new LanmeiCounselorProblem())->getProblemInfoById($answerState['cp_id'], 'uid,problem_status');

        if ($problemData['problem_status'] != $uid)
        {   // 判断问题是不是自己提问题的
            throw new ApiException('服务异常', 200, config('code.error'));
        }

        if (in_array($problemData['problem_status'], [3, 4]))
        {   // 判断问题是不是在 待回答|待结算 状态
            throw new ApiException('服务异常', 200, config('code.error'));
        }

        \DB::beginTransaction();
        try
        {
            $time = time();
            $caUpdate = ['state' => 4, 'inform_time' => $time];
            $res = $this->save($caUpdate, ['id' => $caId]);

            $informData = [
                'create_time' => $time,
                'ca_id' => $caId,
                'tid' => $tid,
                'content' => $content,
                'uid' => $uid,
                'status' => 0
            ];

            $informRes = (new LanmeiCounselorInform())->create($informData);

            if ($res && $informRes)
            {
                \DB::commit();
            } else
            {
                throw new ApiException('服务异常，举报失败！', config('code.error'));
            }
        }
        catch (Exception $e)
        {
            \DB::rollback();
            throw new ApiException('服务异常，举报失败！', config('code.error'));
        }

        // 更新缓存
        CacheManage::getInstance()->setCacheConfig('counselor_problem_answer', $caId)->setCache($caUpdate, 'details', true);
    }

    /**
     * 答案评论
     * @param $param
     * @param $uid
     * @throws ApiException
     * @throws \Exception
     */
    public function answerToComment($param, $uid)
    {
        // 获取答案信息
        $answerData = current($this->batchGetInfoByIds($param['ca_id'], 'cp_id,c_id'));

        if (!$answerData)
        {
            throw new ApiException('答案不存在', 200, config('code.error'));
        }
        // 获取问题信息
        $problemData = (new LanmeiCounselorProblem())->getProblemInfoById($answerData['cp_id'], 'uid,problem_status');

        if (empty($problemData) || $problemData['uid'] != $uid)
        {
            throw new ApiException('答案不存在', 200, config('code.error'));
        }

        if (!in_array($problemData['problem_status'], [3, 4]))
        {
            throw new ApiException('答案过了可评价时间', 200, config('code.error'));
        }

        \DB::beginTransaction();
        try
        {
            $answerCommentModel = new LanmeiCounselorAnswerComment();
            $commentTagModel = new LanmeiCommentTag();

            $commentData = [
                'create_time' => time(),
                'grade' => $param['grade'],
                'content' => $param['content'],
                'ca_id' => $param['ca_id'],
                'uid' => $uid,
                'c_id' => $answerData['c_id']
            ];
            $where = [];
            if ($param['id'])
            {   // 更新
                $where = ['id' => $param['id'], 'ca_id' => $param['ca_id']];
                // 删除 评论标签
                $commentTagModel->where('cac_id', $param['id'])->delete();
            }
            $res = $answerCommentModel->where($where)->update($commentData);

            $commentTags = [];
            foreach ($param['tag_ids'] as $tagItem)
            {
                $commentTags[] = [
                    'create_time' => time(),
                    'tid' => $tagItem,
                    'c_id' => $answerData['c_id'],
                    'cac_id' => $answerCommentModel->id ?? $param['id']
                ];
            }

            $ctRes = $commentTagModel->create($commentTags);

            if (!$where)
            {
                $this->save(['is_comment' => 1], ['id' => $param['ca_id']]);
            }

            if ($res && $ctRes)
            {
                \DB::commit();
            } else
            {
                throw new ApiException('服务异常', config('code.error'));
            }
        }
        catch (Exception $e)
        {
            \DB::rollback();
            throw new ApiException('服务异常', 200, config('code.error'));
        }
        // 更新缓存
        CacheManage::getInstance()->setCacheConfig('counselor_problem_answer', $param['ca_id'])
            ->setCache(['is_comment' => 1], 'details', true);
    }

    /**
     * 查看评论详情
     * @param $caId
     * @return array
     * @throws ApiException
     * @throws Exception
     * @throws \Exception
     */
    public static function getCommentInfo($caId)
    {
        try
        {   // 获取评价信息
            $commentData = (new LanmeiCounselorAnswerComment())->where('ca_id', $caId)->select('id','grade','content','uid')->first();
        }
        catch (Exception $e)
        {
            throw new ApiException('服务异常', 200, config('code.error'));
        }

        $tags = $commentData->comments()->get(['tid']);

        $tagData = LanmeiTag::getTagData(2);

        $tagsInfo = [];
        foreach ($tags as $tagId)
        {
            $tagsInfo[] = [
                'id' => $tagId,
                'tag_name' => $tagData[$tagId]
            ];
        }

        return [
            'grade' => $commentData['grade'],
            'content' => $commentData['content'],
            'id' => $commentData['id'],
            'tag_data' => $tagsInfo,
            'is_default' => $commentData['uid'] > 0 ? 0 : 1, // 是不是默认评价 0不是 1是
        ];
    }

    /**
     * 答案围观
     * @param $uid
     * @param $caId
     * @param $oid
     * @return int
     * @throws Exception
     */
    public function answerRead($uid, $caId, $oid)
    {
        $readData = [
            'ca_id' => $caId,
            'uid' => $uid,
            'order_id' => $oid,
            'create_time' => time()
        ];

        $res = (new LanmeiCounselorAnswerOnlooker())->createAnswerRead($readData);

        return $res;
    }

    /**
     * 通过数据库查询咨询师所有回答过的问题id
     * @param $cid
     * @return array
     * @throws ApiException
     */
    public function getCounselorAnswerCpidsByData($cid)
    {
        try
        {
            $data = $this->where('c_id', $cid)->whereIn('state', [0, 1, 4])->pluck('cp_id')->toArray();
        }
        catch (Exception $e)
        {
            throw new ApiException('服务异常', 200, config('code.error'));
        }

        return $data;
    }

    /**
     * 获取 咨询师 回答过的问题ID
     * @param $cid
     * @return array
     * @throws \Exception
     */
    public function getCounselorAnswerToProblemCpIds($cid)
    {
        $result = CacheManage::getInstance()->setCacheConfig('counselor_answer_problem_cpids', $cid)
            ->sGetIocData('list', function () use ($cid)
            {
                return $this->getCounselorAnswerCpidsByData($cid);
            });

        return $result;
    }

    /**
     * 更新 咨询师 回答过的问题ID
     * @param $cid
     * @param $cpId
     * @throws \Exception
     */
    public function setCounselorAnswerToProblemCpIds($cid, $cpId)
    {
        CacheManage::getInstance()->setCacheConfig('counselor_answer_problem_cpids', $cid)
            ->sAddIocData([$cpId], 'list', function () use ($cid)
            {
                return $this->getCounselorAnswerCpidsByData($cid);
            });
    }

    /**
     * 获取咨询师师问答回复页面--所有的问题ID
     * @param $cid
     */
    protected function getCounselorAnswerIdsListAll($cid)
    {
        $this->where('c_id', $cid)->get(['sort', 'id']);
    }

    /**
     * 获取咨询师所有回答的答案 分页查
     * @param $cid
     * @param bool $isSelf
     * @return array
     * @throws ApiException
     */
    public function getCounselorAnswerList($cid, $isSelf = false)
    {
        try
        {
            $where = ['c_id' => $cid];
            if (!$isSelf)
            {
                $where['state'] = 0;
                $where['status'] = 1;
            }
            $answerList = $this->where('c_id', $cid)
            ->select('id','create_time','cp_id','is_accept','read_num','is_comment','state','sort','price')
            ->orderBy('sort','desc')
            ->paginate(10)->toArray();
        }
        catch (Exception $e)
        {
            throw new ApiException('服务异常', 100, config('code.error'));
        }

        return $answerList;
    }

    /**
     * 通过问题ID 获取所有的问题信息 和 评分
     * @param $cpId
     * @param string $filed
     * @return mixed
     * @throws ApiException
     */
    public function getAnswerListByCpid($cpId, $filed = '*')
    {
        try
        {
            $data =  $this->from('counselor_answer as ca')
                ->join('counselor_answer_comment as cac', 'ca.id','=','cac.ca_id', 'left')
                ->where('ca.cp_id', $cpId)->get([$filed])->keyBy('id')->toArray();
        }
        catch (Exception $e)
        {
            throw new ApiException('服务异常', 200, config('code.error'));
        }

        return $data;
    }

    /**
     * @param $caIds
     * @return array
     * @throws ApiException
     * @throws Exception
     */
    protected function batchGetInfoByIdsInData($caIds)
    {
        try
        {
            //$data = $this->whereIn('cp_id', $caIds)->where('status', 1)->get(['id','create_time','accept_time','inform_time','cp_id','c_id','answer_type','answer_content','is_accept','read_num','is_comment','status','state','sort','duration','price'])->keyBy('id')->toArray();
            $data = $this->whereIn('cp_id', $caIds)->where('status', 1)->get(['id','create_time','accept_time','inform_time','cp_id','c_id','answer_type','answer_content','is_accept','read_num','is_comment','status','state','sort','duration','price'])->toArray();
        }
        catch (Exception $e)
        {
            throw new ApiException('服务异常', 200, config('code.error'));
        }

        return $data;
    }

    /**
     * 通过答案ID 批量获取答案详情
     * @param $caIds
     * @param $field
     * @return array
     * @throws \Exception
     */
    public function batchGetInfoByIds($caIds, $field)
    {
        $data = CacheManage::getInstance()->setCacheConfig('counselor_problem_answer')
            ->batchGetCache($caIds, function ($ids)
            { 
                return $this->batchGetInfoByIdsInData($ids);
            }, $field, 'list_details');

        return $data;
    }

    /**
     * 数据排序
     * @param $caIds
     * @param $data
     * @return array
     */
    public function dataSort($caIds, $data)
    {
        $resData = [];
        foreach ($caIds as $caId)
        {
            $resData[] = $data[$caId] ?? [];
        }

        return $resData;
    }

    /**
     * 保存多个数据到当前数据对象
     * @access public
     * @param array     $dataSet 数据
     * @param boolean   $replace 是否自动识别更新和写入
     * @return array|false
     */
    public function saveAll($dataSet, $replace = true)
    {

        $result = [];
        \DB::beginTransaction();
        try {
            $pk = 'id';
            if (is_string($pk) && $replace) {
                $auto = true;
            }
            foreach ($dataSet as $key => $data) {
                if (!empty($auto) && isset($data[$pk])) {
                    $result[$key] = self::update($data);
                } else {
                    $result[$key] = self::create($data);
                }
            }
            \DB::commit();
            return $result;
        } catch (\Exception $e) {
            \DB::rollback();
            throw $e;
        }
    }
}